/* SQUIB - Scala's Quirky User Interface Builder 
    Copyright (C) 2008 Tim Dalton

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/
    
import scala.collection.mutable.{HashMap}

package tfd.scala.squib.scenario.scenegraph {

    import java.util.EventObject

    import com.sun.scenario.scenegraph._

    import tfd.scala.squib._

    //object transforms

    trait BuiltNode[T <: SGNode] extends RootTrait with HasDefaultAttributes
        with HasSetterAttributes
        with FiresEventObjectsWithNode
        with FiresMouseEventsWithNode[T]
    {

        def apply(id:String, rest:Any*) = {
            val node = doId(id, newNode)
            processParams(id, rest.elements, node)
            node
        }

        def apply(rest:Any*) = {
            val node = newNode
            processParams(null, rest.elements, node)
            node
        }

        private def processParams(id:String, parms:Iterator[Any], node:SGNode) = {
            var accumulatedAttrs:Attributes = null
            var accumulatedEvents:HashMap[String, (EventObject, SGNode) => Unit] = null
            for (parm <- parms) {
                parm match {
                    case attrs:Attributes => doSetters(id, node, attrs)
                    case evts:HashMap[String, (EventObject, SGNode) => Unit] => doEvents(node, evts)
                    case tup:Tuple2[Symbol, Any] =>
                        tup._2 match {
                            case func:((EventObject, SGNode) => Unit) => {
                                    if (accumulatedEvents == null) {
                                        accumulatedEvents = new HashMap[String, (EventObject, SGNode) => Unit]()
                                    }
                                    accumulatedEvents += tup._1.toString.substring(1).toLowerCase -> func
                                }
                            case any:Any => {
                                    if (accumulatedAttrs == null) {
                                        accumulatedAttrs = new Attributes
                                    }
                                    accumulatedAttrs += tup
                                }
                        }
                    case unk:Any => throw new Exception(unk.toString + " doesn't represent attributes or event for " + this.getClass)
                }
            }
            if (accumulatedAttrs != null) doSetters(id, node, accumulatedAttrs)
            if (accumulatedEvents != null) doEvents(node, accumulatedEvents)
        }

        def newNode:T

        def events[E <: EventObject](idee:String, evts:Tuple2[Symbol, (E, SGNode) => Unit]*) = {
            val eventMap = new HashMap[String, (E, SGNode) => Unit]()
            eventMap ++ {for (evt <- evts.elements) yield (evt._1.toString.substring(1).toLowerCase, evt._2)}
            doEvents(id[T](idee), eventMap)
        }

        def id(idee: String):T = id[T](idee)
    }
}